import { ProjectInfo, SourceGNConfig } from '../types/FuzzTypes';
import { FuzzNameUtils } from '../utils/FuzzNameUtils';
import { getInferenceEngine } from '../../../../core/inference/OpenHarmonyInferenceEngine';
import { UltraDeepFuzzPromptEnhancer } from './UltraDeepFuzzPromptEnhancer';

/**
 * Fuzz Prompt 构建器
 * 负责构建发送给 LLM 的 Prompt
 * 
 * 集成智能推理引擎，提升 GN 配置准确性
 */
export class FuzzPromptBuilder {
    private static inferenceEngine = getInferenceEngine();
    /**
     * 获取 Apache 2.0 版权声明（C/C++ 风格）
     */
    private static getCopyrightCpp(year: number): string {
        return `/*
 * Copyright (c) ${year} Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */`;
    }

    /**
     * 获取 Apache 2.0 版权声明（GN 风格）
     */
    private static getCopyrightGN(year: number): string {
        return `# Copyright (c) ${year} Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.`;
    }

    /**
     * 获取 Apache 2.0 版权声明（XML 风格）
     */
    private static getCopyrightXML(year: number): string {
        return `<!-- Copyright (c) ${year} Huawei Device Co., Ltd.
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

-->`;
    }

    /**
     * 构建 .h 文件生成 Prompt
     */
    public static buildHeaderPrompt(fuzzerName: string): string {
        const currentYear = new Date().getFullYear();
        const copyright = this.getCopyrightCpp(currentYear);
        
        return `生成 OpenHarmony Fuzz 测试的头文件 ${fuzzerName}.h

**必须使用以下完整的版权声明（不能省略任何内容）：**
${copyright}

**然后是头文件保护和宏定义：**
#ifndef ${fuzzerName.toUpperCase()}_H
#define ${fuzzerName.toUpperCase()}_H

#define FUZZ_PROJECT_NAME "${fuzzerName}"

#endif

**❌ 禁止：**
- 不要缩短或省略版权声明
- 不要注释掉任何版权内容
- 不要使用 "... 省略版权" 这样的标记

直接输出完整代码，不要任何解释或markdown标记。`;
    }

    /**
     * 构建 .cpp 文件生成 Prompt
     */
    public static buildCppPrompt(
        fuzzerName: string,
        baseName: string,
        sourceCode: string,
        sourceGNConfig: SourceGNConfig | null
    ): string {
        const currentYear = new Date().getFullYear();
        const copyright = this.getCopyrightCpp(currentYear);
        const gnConfigInfo = sourceGNConfig ? 
            `源文件的关键依赖：\n${sourceGNConfig.external_deps.slice(0, 5).join(', ')}` : 
            '参考原 BUILD.gn';
        
        const basePrompt = `生成 OpenHarmony Fuzz 测试的实现文件 ${fuzzerName}.cpp

**源文件：** ${baseName}.cpp
**依赖信息：** ${gnConfigInfo}

**🎯 目标函数签名（请仔细分析参数类型）：**
\`\`\`cpp
${sourceCode.substring(0, 500)}
\`\`\`

**⚠️ 关键要求：**
1. **仔细分析**上述函数的参数类型（int32_t、bool、std::string、指针、引用等）
2. 根据参数类型**智能计算**所需的最小数据大小
3. 使用 **FuzzedDataProvider** 解析不同类型的参数
4. 为每种参数类型使用**正确的解析方法**（不要所有函数都用相同的模板）

**必须使用以下完整的版权声明作为文件开头：**
${copyright}

**然后是必要的 include：**
#include "${fuzzerName}.h"
#include <securec.h>
#include <cstddef>
#include <cstdint>

**然后实现 Fuzz 测试函数（必须根据目标函数签名智能生成）：**
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
    // 🎯 关键要求：根据目标函数的参数类型，智能计算所需的最小数据大小
    // 示例：
    // - 如果函数有2个int32_t参数：size < 2 * sizeof(int32_t)
    // - 如果函数有字符串参数：size < sizeof(size_t) + 字符串最小长度
    // - 如果函数有bool参数：size < sizeof(bool)
    // - 如果函数有多种类型：累加所有参数的大小
    
    // ❌ 不要所有函数都用 sizeof(int32_t)，必须根据实际参数调整
    if (data == nullptr || size == 0) {
        return 0;
    }
    
    // 🔥 强烈推荐使用 FuzzedDataProvider 解析参数（最佳实践）
    // #include <fuzzer/FuzzedDataProvider.h>
    // FuzzedDataProvider fdp(data, size);
    
    // 根据目标函数的参数类型，使用对应的方法：
    // - std::string 参数: fdp.ConsumeRandomLengthString(max_len)
    // - int32_t 参数: fdp.ConsumeIntegral<int32_t>()
    // - bool 参数: fdp.ConsumeBool()
    // - uint8_t* 参数: fdp.ConsumeBytes<uint8_t>(length)
    // - enum 参数: fdp.ConsumeEnum<EnumType>()
    
    // 调用目标函数进行测试
    // TargetFunction(param1, param2, ...);
    
    return 0;
}

**❌ 禁止：**
- 不要缩短或省略版权声明
- 不要注释掉任何版权内容
- 版权必须完整且在文件最开头

直接输出完整代码，不要任何解释或markdown标记。`;
        
        // 🔮 使用超深度学习数据增强Prompt
        try {
            const enhancedPrompt = UltraDeepFuzzPromptEnhancer.enhancePrompt(
                basePrompt,
                sourceCode,
                baseName
            );
            return enhancedPrompt;
        } catch (error) {
            console.error('[FuzzPromptBuilder] ⚠️ Prompt增强失败，使用原始Prompt', error);
            return basePrompt;
        }
    }

    /**
     * 构建 BUILD.gn 文件生成 Prompt
     * 
     * 集成智能推理引擎，自动推断 external_deps
     */
    public static buildBuildGnPrompt(
        fuzzerName: string,
        projectInfo: ProjectInfo,
        fuzzConfigPath: string,
        sourceGNConfig: SourceGNConfig | null,
        sourceCode?: string
    ): string {
        const currentYear = new Date().getFullYear();
        const copyright = this.getCopyrightGN(currentYear);
        
        // 使用推理引擎增强依赖推断
        let enhancedDeps = sourceGNConfig?.deps || [];
        let enhancedExternalDeps = sourceGNConfig?.external_deps || [];
        let enhancedIncludeDirs = sourceGNConfig?.include_dirs || [];
        
        if (sourceCode) {
            // 分析源代码，提取 includes
            const analysis = this.inferenceEngine.analyzeSourceCode(sourceCode);
            
            // 推断 external_deps
            const inferredExternalDeps = this.inferenceEngine.inferExternalDeps(analysis.includes);
            enhancedExternalDeps = [...new Set([...enhancedExternalDeps, ...inferredExternalDeps])];
            
            // 根据代码类型推荐基础依赖
            const codeType = analysis.hasService ? 'service' : 
                           analysis.hasClient ? 'client' : 
                           analysis.ndkInterfaces.length > 0 ? 'ndk' : 'default';
            const recommendedDeps = this.inferenceEngine.getRecommendedDeps(codeType);
            enhancedExternalDeps = [...new Set([...enhancedExternalDeps, ...recommendedDeps])];
            
            console.log(`[FuzzPromptBuilder] 🧠 智能推断完成:`);
            console.log(`  - 检测到 ${analysis.includes.length} 个 include`);
            console.log(`  - 检测到 ${analysis.ndkInterfaces.length} 个 NDK 接口`);
            console.log(`  - 推断 external_deps: ${inferredExternalDeps.join(', ')}`);
            console.log(`  - 推荐 ${codeType} 类型依赖: ${recommendedDeps.join(', ')}`);
        }
        
        const depsInfo = `deps: ${enhancedDeps.join(', ')}\nexternal_deps: ${enhancedExternalDeps.join(', ')}`;
        const camelCaseName = FuzzNameUtils.toCamelCase(fuzzerName);
        
        // 构建GN路径格式的 fuzz_config_file（使用路径变量）
        const gnFuzzConfigPath = `\${${projectInfo.pathVariable}}/${fuzzConfigPath}`;
        
        // 提取 include_dirs 示例（转换为 GN 路径格式）
        const includeDirsExample = enhancedIncludeDirs.length > 0 
            ? enhancedIncludeDirs.slice(0, 5).map(dir => {
                // 如果已经是 GN 路径（//开头），直接使用；否则，转换
                if (dir.startsWith('//')) {
                    return `    "${dir}"`;
                }
                // 否则，假设是相对路径，转换为GN路径
                return `    "//${projectInfo.subsystem}/${projectInfo.module}/${dir}"`;
              }).join(',\n')
            : `    "//${projectInfo.subsystem}/${projectInfo.module}/include"`;
        
        return `生成 OpenHarmony Fuzz 测试的 BUILD.gn 文件

**项目信息：**
- 子系统：${projectInfo.subsystem}
- 模块：${projectInfo.module}
- 路径变量：${projectInfo.pathVariable}
- Fuzzer 名称：${fuzzerName}
- Fuzzer 相对路径：${fuzzConfigPath}
${projectInfo.gniImport ? `- 项目 GNI：${projectInfo.gniImport}` : ''}

**源文件依赖信息：**
${depsInfo}

**必须使用以下完整的版权声明作为文件开头：**
${copyright}

**然后是导入和目标定义（必须包含 fuzz_config_file）：**
import("//build/test.gni")
${projectInfo.gniImport ? `import("${projectInfo.gniImport}")` : ''}

ohos_fuzztest("${camelCaseName}FuzzTest") {
  module_out_path = "${projectInfo.subsystem}/${projectInfo.module}"
  
  # ⚠️ fuzz_config_file 是必须的！必须使用路径变量！
  fuzz_config_file = "${gnFuzzConfigPath}"
  
  sources = [ "${fuzzerName}.cpp" ]
  
  # ⚠️ include_dirs 必须使用 GN 路径格式（以 // 开头），禁止使用绝对路径！
  include_dirs = [
${includeDirsExample}
  ]
  
  deps = [
    # 完整列出所有依赖，使用完整的GN路径格式
  ]
  
  external_deps = [
    # 完整列出所有外部依赖
    ${enhancedExternalDeps.slice(0, 10).map(dep => `"${dep}"`).join(',\n    ')}
  ]
}

group("fuzztest") {
  testonly = true
  deps = [ ":${camelCaseName}FuzzTest" ]
}

**关键要求（必须严格遵守）：**
1. ✅ module_out_path 必须是 "${projectInfo.subsystem}/${projectInfo.module}"
2. ✅ fuzz_config_file 必须使用路径变量："\${${projectInfo.pathVariable}}/${fuzzConfigPath}"
3. ✅ include_dirs 中的所有路径必须以 "//" 开头（GN路径格式）
4. ✅ 禁止使用任何本地绝对路径（如 C:\\、/AI_Dev/ 等）
5. ✅ 如果有项目 GNI import，要在 import("//build/test.gni") 后添加

**路径格式示例：**
✅ 正确："//${projectInfo.subsystem}/${projectInfo.module}/services/xxx"
✅ 正确："\${${projectInfo.pathVariable}}/test/fuzztest"
❌ 错误："AI_Dev/code/xxx"（绝对路径）
❌ 错误："C:/Users/xxx"（本地路径）
❌ 错误："services/xxx"（缺少 // 前缀）

**❌ 禁止：**
- 不要省略版权声明的任何部分
- 不要省略 fuzz_config_file 字段（这是最重要的！）
- 不要省略依赖项，不要使用 "其余XX项省略"
- 不要使用本地绝对路径
- 版权必须完整且在文件最开头

直接输出完整代码，不要任何解释或markdown标记。`;
    }

    /**
     * 构建 project.xml 文件生成 Prompt
     */
    public static buildProjectXmlPrompt(): string {
        const currentYear = new Date().getFullYear();
        const copyright = this.getCopyrightXML(currentYear);
        
        return `生成 OpenHarmony Fuzz 测试的 project.xml 配置文件

**必须使用以下完整格式（版权在最前面）：**
${copyright}
<?xml version="1.0" encoding="utf-8"?>
<fuzz_config>
  <fuzztest>
    <max_len>1000</max_len>
    <max_total_time>300</max_total_time>
    <rss_limit_mb>4096</rss_limit_mb>
  </fuzztest>
</fuzz_config>

**❌ 禁止：**
- 不要把版权放在 <?xml> 之后
- 不要省略版权声明的任何部分
- 版权注释必须在文件最开头

直接输出完整代码，不要任何解释或markdown标记。`;
    }

    /**
     * 构建 corpus/init 文件生成 Prompt
     */
    public static buildCorpusInitPrompt(): string {
        const currentYear = new Date().getFullYear();
        const copyright = this.getCopyrightCpp(currentYear);
        
        return `生成 OpenHarmony Fuzz 测试的 corpus/init 种子文件

**必须使用以下完整格式：**
${copyright}

FUZZ

**❌ 禁止：**
- 不要省略版权声明的任何部分
- 版权声明必须完整
- 最后一行必须是 FUZZ

直接输出完整内容，不要任何解释或markdown标记。`;
    }
}

